package com.jh.paymentchannel.business.impl;

import cn.jh.common.utils.CommonConstants;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.ImmutableMap;
import com.jh.paymentchannel.business.BankCard4AuthBusiness;
import com.jh.paymentchannel.pojo.BankCard4Auth;
import com.jh.paymentchannel.pojo.BankCard4AuthRoute;
import com.jh.paymentchannel.pojo.BankCardLocation;
import com.jh.paymentchannel.repository.BankCard4AuthRepository;
import com.jh.paymentchannel.repository.BankCard4AuthRouteRepository;
import com.jh.paymentchannel.repository.BankCardLocationRepository;
import com.jh.paymentchannel.util.PaymentChannelConstants;
import io.jsonwebtoken.lang.Objects;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Service
public class BankCard4AuthBusinessImpl implements BankCard4AuthBusiness {

    private static final Logger log = LoggerFactory.getLogger(BankCard4AuthBusinessImpl.class);

    @Autowired
    private BankCard4AuthRepository bankCard4repository;

    @Autowired
    private BankCard4AuthRouteRepository bankCard4Routerepository;

    @Autowired
    private BankCardLocationRepository bankCardLocationrepository;


    @Autowired
    private EntityManager em;


    @Override
    public List<BankCard4Auth> findAllBankCard4s(Pageable pageable) {
        Page<BankCard4Auth> page = bankCard4repository.findAll(pageable);
        return page.getContent();
    }

    @Override
    public List<BankCard4Auth> findAllSuccessBankCard4s(Pageable pageable) {
        return bankCard4repository.findBankCard4AuthSuccess(pageable);
    }

    @Override
    public BankCard4Auth findBankCard4AuthByCard(String bankcard) {
        return bankCard4repository.findBankCard4AuthByCard(bankcard);
    }

    @Override
    public BankCard4Auth findBankCard4AuthByMobile(String mobile) {
        return bankCard4repository.findBankCard4AuthByMobile(mobile);
    }


    @Override
    @Transactional
    @SuppressWarnings("unchecked")
    public BankCard4Auth bankCard4Auth(
            String mobile, String bankCard, String idcard, String realname, String jhKey, String bankUrl) {

        BankCard4AuthRoute bankCard4AuthRoute = bankCard4Routerepository.getCurActiveBankCard4Channel();

        String authChannel = bankCard4AuthRoute.getCurChannel();
        String resultString = "{}";

        BankCard4Auth bankCard4Auth = bankCard4repository.findBankCard4AuthByCard(bankCard);
//        BankCard4Auth bankCard4Auth = bankCard4repository.getBankCard4AuthByCard(bankCard, 1);

        if (bankCard4Auth != null && bankCard4Auth.getResCode() == 1) {
            // 卡已经验证通过，无需重复验证
//            if (1 == bankCard4Auth.getResCode()) {
//                return bankCard4Auth;
//            }
            // 验证失败的卡号不需要重复请求服务商验证
            if (Objects.nullSafeEquals(mobile, bankCard4Auth.getMobile()) &&
                    Objects.nullSafeEquals(idcard, bankCard4Auth.getIdcard()) &&
                    Objects.nullSafeEquals(realname, bankCard4Auth.getRealname())) {
                return bankCard4Auth;
            }
            String existMobile = bankCard4Auth.getMobile();
            if (!mobile.equals(existMobile)) {
                log.info("银行卡4要素验证失败：mobile = {}, existMobile = {}, bankCard = {}, idcard = {}, realname = {}", mobile, existMobile, bankCard, idcard, realname);
                return null;
            }
        }
        // 当前要验证的卡号没有信息
        if (bankCard4Auth == null) {
            bankCard4Auth = new BankCard4Auth();
            bankCard4Auth.setBankcard(StringUtils.trimToEmpty(bankCard));
            bankCard4Auth.setIdcard(StringUtils.trimToEmpty(idcard));
            bankCard4Auth.setMobile(StringUtils.trimToEmpty(mobile));
            bankCard4Auth.setRealname(StringUtils.trimToEmpty(realname));
        }

        try {
            if (authChannel.equalsIgnoreCase(PaymentChannelConstants.BANKCARD4_CHANNEL_1)) {
                resultString = JuHeAPIBankCard4AuthService.bankCard4AuthJuhe(mobile, bankCard, idcard, realname, jhKey,bankUrl);
                log.trace(PaymentChannelConstants.BANKCARD4_CHANNEL_1 + "返回：" + resultString);
            }
            if (authChannel.equalsIgnoreCase(PaymentChannelConstants.BANKCARD4_CHANNEL_2)) {

                resultString = JuHeAPIBankCard4AuthService.bankCard4AuthAli(mobile, bankCard, idcard, realname);
                log.trace(PaymentChannelConstants.BANKCARD4_CHANNEL_2 + "返回：" + resultString);
            }

            bankCard4Auth.setAuthTime(new Date());

            Map<String, Object> respMap = JSON.parseObject(resultString,
                    new TypeReference<Map<String, Object>>() {}.getType());
            if (authChannel.equals(PaymentChannelConstants.BANKCARD4_CHANNEL_1)) {
                int errorCode = (Integer) respMap.getOrDefault("error_code", -1);
                if (errorCode == 0) {
                    Map<String, Object> resultMap = ImmutableMap.of();
                    Object resultObj = respMap.get("result");
                    if (resultObj instanceof Map) {
                        resultMap = (Map<String, Object>) resultObj;
                    }
                    if (resultMap.isEmpty()) {
                        bankCard4Auth.setResCode(2);
                    }
                        bankCard4Auth.setJobid((String) resultMap.get("jobid"));
                        bankCard4Auth.setMessage((String) resultMap.get("message"));
                        // juhe service res 2: verify fail
                        String resCodeStr = (String) resultMap.getOrDefault("res", "2");
                        bankCard4Auth.setResCode(NumberUtils.toInt(resCodeStr, 2));
                        if ("1".equals(resCodeStr)) {
                            bankCard4Auth.setMobile((String) resultMap.get("mobile"));
                        } else {
                            bankCard4Auth.setMobile(mobile);
                        }
                } else {
                    bankCard4Auth.setMessage((String) respMap.get("reason"));
                    bankCard4Auth.setResCode(2);
                }

            }
            if (authChannel.equals(PaymentChannelConstants.BANKCARD4_CHANNEL_2)) {
                if ("0".equals(String.valueOf(respMap.get("status")))) {
                    Map<String, Object> resultMap = ImmutableMap.of();
                    Object resObject = respMap.get("result");
                    if (resObject instanceof Map) {
                        resultMap = (Map<String, Object>) resObject;
                    }
                    if (resultMap.containsKey("verifystatus")) {
                        bankCard4Auth.setMessage((String) resultMap.get("verifymsg"));
                        if ("0".equals(resultMap.getOrDefault("verifystatus", "-1"))) {
                            bankCard4Auth.setResCode(1);
                        } else {
                            bankCard4Auth.setResCode(2);
                        }
                    }
                } else {
                    bankCard4Auth.setMessage((String) respMap.get("msg"));
                    bankCard4Auth.setResCode(2);
                }
            }
        } catch (Exception e) {
            log.error("四要素校验错误:: {}\n请求第三方返回：{}", e.getMessage(), resultString);
            bankCard4Auth.setMessage("信息有误");
            bankCard4Auth.setResCode(2);
        }

        bankCard4repository.save(bankCard4Auth);
        em.flush();

        return bankCard4Auth;

    }

    @Transactional
    @Override
    @SuppressWarnings("unchecked")
    public BankCardLocation findCardLocation(String cardId, String jhKey, String bankUrl) {

        /* 判断cardid是否已经验证过了*/
        BankCardLocation location = bankCardLocationrepository.getCurBankCardLocation(cardId);
        if (location != null && location.getId() > 0 && !StringUtils.isBlank(location.getProvince())) {
            return location;
        } else {

            String result = JuHeAPIBankCard4AuthService.bankCardLocation(cardId, jhKey, bankUrl);

            Map<String, Object> respMap = JSON.parseObject(result,
                    new TypeReference<Map<String, Object>>() {}.getType());

            BankCardLocation bankCardLocation = new BankCardLocation();
            int errorCode = (Integer) respMap.getOrDefault("error_code", -1);
            if (0 == errorCode) {
                Map<String, Object> resultMap = ImmutableMap.of();
                Object resultObj = respMap.get("result");
                if (resultObj instanceof Map) {
                    resultMap = (Map<String, Object>) resultObj;
                }
                if (!resultMap.isEmpty()) {
                    bankCardLocation.setBankLocation(null == resultMap.get("bank") ? MapUtils.getString(resultMap,"bankname") : resultMap.get("bank").toString());
                    bankCardLocation.setCardid(cardId);
                    bankCardLocation.setCreateTime(new Date());
                    bankCardLocation.setBankname(MapUtils.getString(resultMap,"bankname"));
                    bankCardLocation.setAbbreviation(MapUtils.getString(resultMap,"abbreviation"));
                    if (bankUrl.equalsIgnoreCase(CommonConstants.BANK_ASCRIPTION_URL)) {
                        bankCardLocation.setLogo(MapUtils.getString(resultMap,"banklogo"));
                    } else {
                        bankCardLocation.setLogo(MapUtils.getString(resultMap,"logo"));
                    }
                    bankCardLocation.setType(MapUtils.getString(resultMap,"cardtype"));
                    bankCardLocation.setCardtype(MapUtils.getString(resultMap,"cardtype"));
                    bankCardLocation.setNature(MapUtils.getString(resultMap,"nature"));
                    bankCardLocation.setInfo(MapUtils.getString(resultMap,"info"));
                    String province = MapUtils.getString(resultMap, "province");
                    if (StringUtils.isEmpty(province)) {
                        province = "信用卡中心";
                    }
                    bankCardLocation.setProvince(province);
                    String city = MapUtils.getString(resultMap, "city");
                    if (StringUtils.isEmpty(city)) {
                        city = "信用卡中心";
                    }
                    bankCardLocation.setCity(city);
                }
            }
            bankCardLocation.setErrorCode(String.valueOf(errorCode));
            bankCardLocation.setReason((String) respMap.getOrDefault("reason", ""));
            bankCardLocation = bankCardLocationrepository.save(bankCardLocation);
            em.flush();
            return bankCardLocation;
        }
    }


}
